using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;


namespace TacticalGridWars
{
    /// <summary>
    /// Holds a List of Soldier objects and draws it
    /// </summary>
    public class Team : DrawableGameComponent
    {
        #region MemberData
        private SpriteBatch spriteBatch;
        private Texture2D selectorTexture;
        private Texture2D soldierTexture;
        private SpriteFont font;
        private SpriteFont smallfont;
        private int selected; 
        #endregion

        #region Properties
        public List<Soldier> TeamList { get; set; }
        public int ShotsFired { get; set; }
        public int Hits { get; set; }
        public double HitPercent 
        { 
            get { return (double)Hits / (double)ShotsFired; }
        }
        public string Name { get; set; }
        public Color TeamColor { get; set; }
        public int TotalMoves { get; set; }
        public bool AllDead { get; set; }
        public bool Active { get; set; }
        public bool NoMovesLeft { get; set; }

        public Soldier SelectedSoldier
        {
            get
            {
                return TeamList[selected];
            }
            set
            {
                TeamList[selected] = value;
            }
        } 
        #endregion

        public Team(Game game, Color teamColor, string name, bool active = false)
            : base(game)
        {
            this.spriteBatch = new SpriteBatch(game.GraphicsDevice);
            this.TeamColor = teamColor;
            TeamList = new List<Soldier>();
            selected = 0;
            Active = active;
            AllDead = false;
            this.Name = name;
            ShotsFired = 0;
            Hits = 0;
        }

        protected override void LoadContent()
        {
            selectorTexture = this.Game.Content.Load<Texture2D>("selector");
            soldierTexture = this.Game.Content.Load<Texture2D>("soldier");
            font = this.Game.Content.Load<SpriteFont>("font");
            smallfont = this.Game.Content.Load<SpriteFont>("smallfont");
            base.LoadContent();
        }

        /// <summary>
        /// Allows the game component to update itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public override void Update(GameTime gameTime)
        {
            AllDead = true;
            TotalMoves = 0;
            foreach (Soldier soldier in TeamList)
            {
                TotalMoves += soldier.Moves;
                if (!soldier.Dead)
                {
                    AllDead = false;
                }
            }
            if (TotalMoves == 0)
            {
                NoMovesLeft = true;
            }
            else
            {
                NoMovesLeft = false;
            }
            base.Update(gameTime);
        }

        public override void Draw(GameTime gameTime)
        {
            spriteBatch.Begin();

            foreach (Soldier soldier in TeamList)
            {
                if (soldier.Selected && Active)
                {
                    spriteBatch.Draw(selectorTexture, new Vector2(soldier.XPos * 50 + 5, soldier.YPos * 50 + 5), TeamColor * 0.2f);
                }
                else if (soldier.Attackable)
                {
                    spriteBatch.Draw(selectorTexture, new Vector2(soldier.XPos * 50 + 5, soldier.YPos * 50 + 5), Color.Red);
                    spriteBatch.DrawString(smallfont, (soldier.HitChance * 100).ToString("F") + "%", new Vector2(soldier.XPos * 50 + 50, soldier.YPos * 50), Color.Red);
                }
                if (soldier.Dead)
                {
                    spriteBatch.Draw(soldierTexture, new Vector2(soldier.XPos * 50 + 20, soldier.YPos * 50 + 5), TeamColor * 0.10f);
                }
                else
                {
                    spriteBatch.Draw(soldierTexture, new Vector2(soldier.XPos * 50 + 20, soldier.YPos * 50 + 5), TeamColor * 0.75f); 
                }
            }

            spriteBatch.End();
            base.Draw(gameTime);
        }

        /// <summary>
        /// Goes through the TeamList and sets all Soldiers to have Moves = 2 and to not be Selected = false.
        /// Also sets the team.Active = false.
        /// </summary>
        public void ResetTeam()
        {            
            foreach (Soldier soldier in TeamList)
            {
                if (!soldier.Dead)
                {
                    soldier.Moves = 2;
                }
                soldier.Selected = false;
            }
            Active = false;
        }

        /// <summary>
        /// Change the currently active soldier in the team.
        /// </summary>
        /// <param name="soldier">Soldier to make active</param>
        /// <param name="grid">The Grid that makes up the level</param>
        public void ChangeActiveSoldier(Soldier soldier)
        {
            foreach (Soldier s in TeamList)
            {
                s.Selected = false;                
            }
            TeamList[TeamList.IndexOf(soldier)].Selected = true;
            this.selected = TeamList.IndexOf(soldier);
        }

        /// <summary>
        /// Checks if the player has clicked the hitbox of any soldier in the team.
        /// If so, changes the selected soldier in the team.
        /// </summary>
        /// <param name="x">Clicked x-coordinate</param>
        /// <param name="y">Clicked y-coordinate</param>
        /// <param name="grid">The Grid that makes up the level</param>
        public void DoSoldierSelection(int x, int y)
        {
            foreach (Soldier soldier in TeamList)
            {
                if (soldier.XPos == x && soldier.YPos == y && soldier.Moves > 0)
                {
                    ChangeActiveSoldier(soldier);
                }
            }
        }

        /// <summary>
        /// Goes through the TeamList and checks if any soldier matches the one clicked on and if
        /// that Soldier is attackble.
        /// </summary>
        /// <param name="x">X postion on the Grid</param>
        /// <param name="y">Y position on the Grid</param>
        /// <returns>The attackble soldier if it exists, else null</returns>
        public Soldier CheckAttackableSoldiers(int x, int y)
        {
            foreach (Soldier soldier in TeamList)
            {
                if (soldier.XPos == x && soldier.YPos == y && soldier.Attackable)
                {
                    return soldier;
                }
            }
            return null;
        }

        /// <summary>
        /// Initializes the team by spawning Soldiers on all the spawnpoints
        /// </summary>
        /// <param name="spawns">List with all the available spawnpoints</param>
        /// <param name="grid">The GameGrid to spawn the soldier in</param>
        public void Init(List<Grid.Spawn> spawns, Grid grid)
        {
            TeamList.Clear();
            for (int i = 0; i < spawns.Count; i++)
            {
                TeamList.Add(new Soldier(spawns[i]));
            }
            foreach (Soldier soldier in TeamList)
            {
                grid.Level[soldier.YPos, soldier.XPos].Occupied = true;
            }
        }
    }
}
